define(
   [
      'dojo/_base/declare',
      'dojo/_base/event',
      'dojo/_base/lang',
      'dojo/dom-class',
      'dojo/mouse',
      'dojo/on',
      'dojo/aspect'
   ],
   function(declare, ev, lang, domClass, mouse, on, aspect)
   {
      return declare([],
      {
         mAutoPreventDefault: true,
         expandoClass: "dgrid-expando-icon",
         constructor: function(args)
         {
            // Call Super
            dojo.safeMixin(this, args);
            
            this.mRowHoverTimer     = null;
            this.mRowHoverDeffered  = null;
            var afterSignal = aspect.after(this, "postCreate", lang.hitch(this, function()
            {
               afterSignal.remove();
               this.addSignals();
            }));
         },
         addSignals: function()
         {
            var fIsExpando = function(grid, pEvent)
            {
               for(var i = 0; i < pEvent.target.classList.length; i++)
               {
                  var className = pEvent.target.classList[i];
                  if(className === grid.expandoClass)
                     return true;
               };
               return false;
            };
            
            this.on("dgrid-select", dojo.hitch(this, function(pEvent){
               // get the rows that were just selected
               if(this.rowSelectCallback)
               {
                  var items = new Array();
                  for(var row in pEvent.rows)
                  {
                     if(!pEvent.rows.hasOwnProperty(row))
                        continue;

                     items.push(pEvent.rows[row].data);
                  }
                  this.rowSelectCallback(items, pEvent);
               }

            }));

            this.on("dgrid-deselect", dojo.hitch(this, function(pEvent)
            {
               if(this.rowDeselectCallback)
                  this.rowDeselectCallback(pEvent);
            }));

            this.on(".dgrid:contextmenu", dojo.hitch(this, function(pEvent)
            {
               var onRow = this.row(pEvent);
               if(onRow)
                  return;

               if(this.mAutoPreventDefault)
               {
                  ev.stop(pEvent);
                  pEvent.preventDefault();
               }

               if(this.contextMenuFactory)
               {

                  // create or popup a menu here
                  var pContextMenu = this.contextMenuFactory(pEvent);
                  if(!pContextMenu)
                     return;
                  pContextMenu.startup();
                   pEvent.coords = {
                       x: pEvent.pageX,
                       y: pEvent.pageY
                   };
                  pContextMenu._openMyself(pEvent);
               }

            }));

            this.on(".dgrid-row:click", dojo.hitch(this, function(pEvent)
            {
               if(!this.rowClick || fIsExpando(this, pEvent))
                  return;

               this.rowClick(this.row(pEvent).data, pEvent);
            }));

            this.on(".dgrid-row:dblclick", dojo.hitch(this, function(pEvent)
            {
               if(!this.rowDoubleClick || fIsExpando(this, pEvent))
                  return;

               this.rowDoubleClick(this.row(pEvent).data, pEvent);
            }));

            this.on(".dgrid-header:contextmenu", dojo.hitch(this, function(pEvent){
               if(this.mAutoPreventDefault)
               {
                  ev.stop(pEvent);
                  pEvent.preventDefault(); // prevent default browser context menu
               }
               
               if(this.headerContextmenuFactory)
               {
                  // create or popup a menu here
                  var pContextMenu = this.headerContextmenuFactory(pEvent);
                  if(!pContextMenu)
                     return;

                  pContextMenu.startup();
                   pEvent.coords = {
                       x: pEvent.pageX,
                       y: pEvent.pageY
                   };
                  pContextMenu._openMyself(pEvent);
               }
               
            }));

            this.on(".dgrid-row:contextmenu", dojo.hitch(this, function(pEvent){
               if(this.mAutoPreventDefault)
               {
                  ev.stop(pEvent);
                  pEvent.preventDefault(); // prevent default browser context menu
               }
               
               if(this.rowContextmenuFactory)
               {
                  // create or popup a menu here
                  var pContextMenu = this.rowContextmenuFactory(this.row(pEvent).data, pEvent);
                  if(!pContextMenu)
                     return;
                  pContextMenu.startup();
                   pEvent.coords = {
                       x: pEvent.pageX,
                       y: pEvent.pageY
                   };
                  pContextMenu._openMyself(pEvent);
               }
               
            }));
            
            this.on(on.selector('.dgrid-content .dgrid-row', mouse.enter), dojo.hitch(this, function(pEvent){
               var pItem = this.row(pEvent).data;
               if(!pItem || !this.rowHoverDeferred || this.mRowHoverTimeoutId)
                  return;
      
               this.mRowHoverTimeoutId = setTimeout(dojo.hitch(this, function()
               {
                  this.mRowHoverDeffered = this.rowHoverDeferred(pItem, pEvent);
                  this.mRowHoverTimeoutId = null;
               }), 1000);

            }));

            this.on(on.selector('.dgrid-content .dgrid-row', mouse.leave), dojo.hitch(this, function(pEvent){
               if(this.rowHoverDestroy)
                  this.rowHoverDestroy(pEvent);
               
               if(this.mRowHoverDeffered)
                  this.mRowHoverDeffered.cancel();
               
               if(this.mRowHoverTimeoutId)
               {
                  clearTimeout(this.mRowHoverTimeoutId);
                  this.mRowHoverTimeoutId = null;
               }
            }));

            this.on(on.selector('.dgrid-header .dgrid-cell', mouse.enter), dojo.hitch(this, function(pEvent){
               if(!this.headerHover || !this.headerHoverDestroy)
                  return;

               this.headerHoverDestroy(pEvent);
               this.headerHover(pEvent);
            }));

            this.on(on.selector('.dgrid-header .dgrid-cell', mouse.leave), dojo.hitch(this, function(pEvent){
               if(!this.headerHover || !this.headerHoverDestroy)
                  return;

               this.headerHoverDestroy(pEvent);
            }));

         }
      });
   }
);
